package com.xhs.service;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.GlobalHistogramBinarizer;
import com.google.zxing.common.HybridBinarizer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Iterator;

/**
 * 二维码检测服务
 *
 * @author xhs
 */
@Slf4j
@Service
public class QrCodeDetectionService {

    private static final String BASE_QR_CODE_DIR = "wxqrcode";

    /**
     * 检测图片是否包含微信二维码
     */
    public boolean isWechatQrCode(String imageUrl) {
        try {
            log.info("开始检测图片二维码: {}", imageUrl);

            // 下载图片
            BufferedImage image = downloadImage(imageUrl);
            if (image == null) {
                log.warn("图片下载失败，无法检测二维码: {}", imageUrl);
                return false;
            }

            log.info("图片下载成功，尺寸: {}x{}", image.getWidth(), image.getHeight());

            // 多种方式检测二维码
            String qrContent = detectQrCodeWithMultipleMethods(image);
            if (StrUtil.isBlank(qrContent)) {
                log.info("未检测到二维码内容: {}", imageUrl);
                return false;
            }

            // 判断是否是微信二维码
            boolean isWechatQr = isWechatQrContent(qrContent);
            log.info("检测到二维码内容: {}, 是否为微信二维码: {}", qrContent, isWechatQr);

            return isWechatQr;
        } catch (Exception e) {
            log.error("检测二维码失败: {}", imageUrl, e);
            return false;
        }
    }

    /**
     * 下载包含微信二维码的图片（指定手机号、文件名和目录名）
     */
    public String downloadWechatQrCodeImageWithDir(String imageUrl, String phoneNumber, String customFileName, String dirName) {
        try {
            // 使用指定的目录名
            Path dirPath = Paths.get(BASE_QR_CODE_DIR, dirName);
            
            if (!Files.exists(dirPath)) {
                Files.createDirectories(dirPath);
                log.info("创建目录: {}", dirPath);
            }

            // 生成文件名，处理特殊字符
            String fileName = sanitizeFileName(customFileName) + ".jpg";
            Path filePath = dirPath.resolve(fileName);

            // 下载图片，使用相同的请求头
            byte[] imageBytes = HttpUtil.createGet(imageUrl)
                    .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
                    .header("Referer", "https://www.xiaohongshu.com/")
                    .header("Accept", "image/webp,image/apng,image/*,*/*;q=0.8")
                    .header("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
                    .header("Accept-Encoding", "gzip, deflate, br")
                    .header("Connection", "keep-alive")
                    .header("Sec-Fetch-Dest", "image")
                    .header("Sec-Fetch-Mode", "no-cors")
                    .header("Sec-Fetch-Site", "cross-site")
                    .timeout(10000)
                    .execute()
                    .bodyBytes();
            
            if (imageBytes == null || imageBytes.length == 0) {
                log.warn("微信二维码图片下载为空: {}", imageUrl);
                return null;
            }
            
            FileUtil.writeBytes(imageBytes, filePath.toFile());

            log.info("微信二维码图片已下载: {}, 大小: {} bytes", filePath, imageBytes.length);
            return filePath.toString();
        } catch (Exception e) {
            log.error("下载微信二维码图片失败: {}, 手机号: {}, 文件名: {}, 目录: {}", imageUrl, phoneNumber, customFileName, dirName, e);
            return null;
        }
    }

    /**
     * 创建目录名：手机号+标准格式时间
     */
    public String createDirectoryName(String phoneNumber) {
        return phoneNumber + "_" + DateUtil.format(new Date(), "yyyy年MM月dd日HH时mm分ss秒");
    }

    /**
     * 下载图片
     */
    private BufferedImage downloadImage(String imageUrl) {
        try {
            log.info("开始下载图片: {}", imageUrl);

            // 使用Hutool的HttpUtil下载，设置必要的请求头（不使用代理）
            byte[] imageBytes = HttpUtil.createGet(imageUrl)
                    .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
                    .header("Referer", "https://www.xiaohongshu.com/")
                    .header("Accept", "image/webp,image/apng,image/*,*/*;q=0.8")
                    .header("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
                    .header("Accept-Encoding", "gzip, deflate, br")
                    .header("Connection", "keep-alive")
                    .header("Sec-Fetch-Dest", "image")
                    .header("Sec-Fetch-Mode", "no-cors")
                    .header("Sec-Fetch-Site", "cross-site")
                    .timeout(10000)
                    .execute()
                    .bodyBytes();

            if (imageBytes == null || imageBytes.length == 0) {
                log.warn("图片下载为空: {}", imageUrl);
                return null;
            }

            log.info("图片下载成功，大小: {} bytes", imageBytes.length);

            // 将字节数组转换为BufferedImage，支持WebP格式
            try (ByteArrayInputStream bis = new ByteArrayInputStream(imageBytes)) {
                BufferedImage image = readImageWithWebPSupport(bis);
                if (image == null) {
                    log.warn("图片格式不支持或损坏: {}", imageUrl);
                    return null;
                }
                log.info("图片解析成功，尺寸: {}x{}", image.getWidth(), image.getHeight());
                return image;
            }
        } catch (Exception e) {
            log.error("下载图片失败: {}", imageUrl, e);
            return null;
        }
    }

    /**
     * 读取图片，支持WebP格式
     */
    private BufferedImage readImageWithWebPSupport(ByteArrayInputStream bis) throws IOException {
        // 首先尝试标准的ImageIO.read
        BufferedImage image = ImageIO.read(bis);
        if (image != null) {
            return image;
        }

        // 如果标准读取失败，尝试使用ImageReader（支持WebP）
        bis.reset();
        try (ImageInputStream iis = ImageIO.createImageInputStream(bis)) {
            Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
            if (readers.hasNext()) {
                ImageReader reader = readers.next();
                try {
                    reader.setInput(iis);
                    image = reader.read(0);
                    log.info("使用ImageReader成功读取图片，格式: {}", reader.getFormatName());
                    return image;
                } finally {
                    reader.dispose();
                }
            }
        }

        log.warn("无法读取图片格式");
        return null;
    }

    /**
     * 使用多种方法检测二维码
     */
    private String detectQrCodeWithMultipleMethods(BufferedImage image) {
        String result = null;

        // 方法1：直接解码原图
        result = decodeQrCode(image);
        if (StrUtil.isNotBlank(result)) {
            log.info("原图直接解码成功");
            return result;
        }

        // 方法2：转换为灰度图后解码
        BufferedImage grayImage = convertToGrayscale(image);
        result = decodeQrCode(grayImage);
        if (StrUtil.isNotBlank(result)) {
            log.info("灰度图解码成功");
            return result;
        }

        // 方法3：二值化处理后解码
        BufferedImage binaryImage = convertToBinary(grayImage);
        result = decodeQrCode(binaryImage);
        if (StrUtil.isNotBlank(result)) {
            log.info("二值化图解码成功");
            return result;
        }

        // 方法4：反色处理后解码
        BufferedImage invertedImage = invertColors(binaryImage);
        result = decodeQrCode(invertedImage);
        if (StrUtil.isNotBlank(result)) {
            log.info("反色图解码成功");
            return result;
        }

        // 方法5：缩放处理后解码
        BufferedImage scaledImage = scaleImage(grayImage, 1.5f);
        result = decodeQrCode(scaledImage);
        if (StrUtil.isNotBlank(result)) {
            log.info("缩放图解码成功");
            return result;
        }

        log.debug("所有解码方法均失败");
        return null;
    }

    /**
     * 解码二维码（使用多种Binarizer）
     */
    private String decodeQrCode(BufferedImage image) {
        try {
            LuminanceSource source = new BufferedImageLuminanceSource(image);

            // 尝试 HybridBinarizer
            try {
                BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
                Result result = new MultiFormatReader().decode(bitmap);
                return result.getText();
            } catch (Exception e) {
                log.debug("HybridBinarizer解码失败");
            }

            // 尝试 GlobalHistogramBinarizer
            try {
                BinaryBitmap bitmap = new BinaryBitmap(new GlobalHistogramBinarizer(source));
                Result result = new MultiFormatReader().decode(bitmap);
                return result.getText();
            } catch (Exception e) {
                log.debug("GlobalHistogramBinarizer解码失败");
            }

        } catch (Exception e) {
            log.debug("解码二维码失败", e);
        }
        return null;
    }

    /**
     * 转换为灰度图
     */
    private BufferedImage convertToGrayscale(BufferedImage image) {
        BufferedImage grayImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
        Graphics2D g2d = grayImage.createGraphics();
        g2d.drawImage(image, 0, 0, null);
        g2d.dispose();
        return grayImage;
    }

    /**
     * 转换为二值图
     */
    private BufferedImage convertToBinary(BufferedImage grayImage) {
        BufferedImage binaryImage = new BufferedImage(grayImage.getWidth(), grayImage.getHeight(), BufferedImage.TYPE_BYTE_BINARY);
        Graphics2D g2d = binaryImage.createGraphics();
        g2d.drawImage(grayImage, 0, 0, null);
        g2d.dispose();
        return binaryImage;
    }

    /**
     * 反色处理
     */
    private BufferedImage invertColors(BufferedImage image) {
        BufferedImage invertedImage = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
        for (int x = 0; x < image.getWidth(); x++) {
            for (int y = 0; y < image.getHeight(); y++) {
                int rgb = image.getRGB(x, y);
                // 反转颜色
                int invertedRgb = 0xFFFFFF - rgb;
                invertedImage.setRGB(x, y, invertedRgb);
            }
        }
        return invertedImage;
    }

    /**
     * 缩放图片
     */
    private BufferedImage scaleImage(BufferedImage image, float scale) {
        int newWidth = (int) (image.getWidth() * scale);
        int newHeight = (int) (image.getHeight() * scale);
        BufferedImage scaledImage = new BufferedImage(newWidth, newHeight, image.getType());
        Graphics2D g2d = scaledImage.createGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2d.drawImage(image, 0, 0, newWidth, newHeight, null);
        g2d.dispose();
        return scaledImage;
    }

    /**
     * 判断是否是微信二维码内容
     */
    private boolean isWechatQrContent(String content) {
        if (StrUtil.isBlank(content)) {
            return false;
        }

        // 微信二维码的特征
        String lowerContent = content.toLowerCase();

        // 明确的微信链接
        if (lowerContent.contains("weixin://") ||
                lowerContent.contains("wxp://") ||
                lowerContent.contains("wx.qq.com") ||
                lowerContent.contains("u.wechat.com") ||
                lowerContent.contains("qr.weixin.qq.com") ||
                lowerContent.startsWith("https://u.wechat.com/") ||
                lowerContent.startsWith("http://u.wechat.com/") ||
                lowerContent.startsWith("https://weixin.qq.com/") ||
                lowerContent.startsWith("http://weixin.qq.com/")) {
            return true;
        }

        // 包含微信关键词
        if (lowerContent.contains("微信") || lowerContent.contains("wechat")) {
            return true;
        }

        // 群相关关键词（更严格的判断）
        if (lowerContent.contains("群") || lowerContent.contains("group")) {
            // 需要同时包含其他微信相关词汇
            return lowerContent.contains("微信") || lowerContent.contains("wechat") ||
                    lowerContent.contains("invite") || lowerContent.contains("加入");
        }

        // 检查是否是微信群二维码的特殊格式
        if (lowerContent.startsWith("https://") && lowerContent.contains("invite")) {
            return true;
        }

        return false;
    }

    /**
     * 清理文件名中的特殊字符
     */
    private String sanitizeFileName(String fileName) {
        if (StrUtil.isBlank(fileName)) {
            return "untitled_" + System.currentTimeMillis();
        }

        // 移除或替换特殊字符
        String sanitized = fileName
                .replaceAll("[\\\\/:*?\"<>|]", "_")  // Windows不允许的字符
                .replaceAll("[\\s]+", "_")          // 空格替换为下划线
                .replaceAll("[‼️❌]", "")           // 移除表情符号
                .replaceAll("_+", "_")              // 多个下划线合并为一个
                .trim();

        // 如果清理后为空，使用默认名称
        if (StrUtil.isBlank(sanitized)) {
            sanitized = "untitled_" + System.currentTimeMillis();
        }

        // 确保文件名不以点开头
        if (sanitized.startsWith(".")) {
            sanitized = "file_" + sanitized;
        }

        // 限制文件名长度
        if (sanitized.length() > 100) {
            sanitized = sanitized.substring(0, 100);
        }

        return sanitized;
    }

}